package com.yunmaple.rabbitmq.receiver;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import com.yunmaple.rabbitmq.entity.Order;
import com.yunmaple.rabbitmq.mapper.OrderMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@Slf4j
public class MessageReceiver {

    final AtomicInteger rc = new AtomicInteger();

    private static ObjectMapper MAPPER = new ObjectMapper();

    @Autowired
    private OrderMapper orderMapper;

    @RabbitListener(queues = "test_queue_1",containerFactory = "rabbitClickListenerContainerFactory")
    public void onMessage(Message message, Channel channel) {
        LocalDate sdf = LocalDate.now();
        int index = rc.incrementAndGet();
        Order order = null;
        try {
            order = MAPPER.readValue(new String(message.getBody()).getBytes("utf-8"),Order.class);
            Order dbOrder = orderMapper.getOrderById(order.getId());
            //订单状态：1待支付；2超时取消；3已支付
            if (dbOrder.getStatus() == 1) {//超时待支付，自动取消订单处理逻辑
                dbOrder.setStatus(2);
                dbOrder.setUsetime(new Date());
                orderMapper.updateOrderInfo(dbOrder);
                log.info("消费数据：{}", dbOrder);
                //最终应答rabbitmq返回，防止消息堵塞
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                log.info("消费数据：（{}======接收消息时间:{}年{}月{}日 {}.......===========从队列读取到消息：《{}》+++++++++++++++++++消费成功++++++++++++++++++++++", index, sdf.getDayOfYear(), sdf.getMonthValue(), sdf.getDayOfMonth(), LocalTime.now(), order);
            } else if (dbOrder.getStatus() == 3 || dbOrder.getStatus() == 2) {//已支付或超时取消状态，直接从队列去除消息，不做处理
                //最终应答rabbitmq返回，防止消息堵塞
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            }
        } catch (Exception e) {
            log.info("重发mq消息:{},失败信息：{}", new String(message.getBody()), e.getMessage());
            try {
                //ack表示失败，要求重新发送
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            } catch (Exception ec) {
                log.info("重发mq消息:++++,失败信息：++++");
            }
        }
    }
}